/*
 ------------------------------------------------------------------------------
	sdlmedia - a test program for a media search library, including test UI.

	Copyright (C) 2011 Pierre Veber
	
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software Foundation,
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
------------------------------------------------------------------------------
*/

#include "common.h"
#include "fastheap.h"
#include "sdlmedia.h"
#include "medialib.h"
#include "flatview.h"

#define THIS_FILTER	TRACE_UI

struct FlatView_t
{
	View_t view;
	
	MediaLib_t*	pLib;

	int nKeyRepeatCount;
	
	int ifHeight;

	int iItemStart;
	int iItemSel;
	int iItemsInPage;
};

/*
 ------------------------------------------------------------------------------
	Flat View UI Specs
------------------------------------------------------------------------------
*/

/* user input */
int _gi_KeyRepeatInitialDelay = 360;
int _gi_KeyRepeatInterval = 15;

int _gi_KeyRepeatCountThreshold = 50; /* 50 repeats before going faster */
int _gi_KeyRepeatSlowMult = 3; /* ignore key intervals amount in slow mode */

/* text */
SDL_Color _gc_FlatViewText = {0xC8, 0xC8, 0xC8};
SDL_Color _gc_FlatViewSelText = {0xFF, 0xFF, 0xFF};
SDL_Color _gc_FlatViewPlayText = {0xCC, 0x99, 0x33};
int _gi_FlatViewItemHeight = 44;

char _gsz_FlatViewTextFont[] = "res/FreeSansBold.ttf";
int _gi_FlatViewTextPtSize = 12;

char _gsz_FlatViewSmallTextFont[] = "res/FreeSans.ttf";
int _gi_FlatViewSmallTextPtSize = 9;


/* selection */

/* scroll */
int _gi_ScrollThreshold	= 2;

/* margins */
int _gi_FlatViewPadding	= 4;
int _gi_FlatViewItemYMargin	= 2;

/*
 ------------------------------------------------------------------------------
	_item_under_mouse(FlatView_t* pView, int x, int y)
------------------------------------------------------------------------------
*/

static int _item_under_mouse(FlatView_t* pView, int x, int y)
{
	if ( (x > _gi_FlatViewPadding) && (x < (_gi_AppWidth - _gi_FlatViewPadding)) )
	{
		if ( (y > _gi_FlatViewPadding) && ( y < (_gi_AppHeight - _gi_FlatViewPadding)) )
		{
			return pView->iItemStart + (y / (pView->ifHeight + _gi_FlatViewItemYMargin));
		}
	}
	return -1;
}

#define SUBFOLDER_MAX_LEN		2048
static char szSubFolder[SUBFOLDER_MAX_LEN+1];

/*
 ------------------------------------------------------------------------------
	Draw Flat View
	UNOPTIMIZED CODE
	TODO:
		cut too long text regarding _gi_FlatViewPadding
------------------------------------------------------------------------------
*/

static void ShowFlatView(SDL_Surface* pScreen, FlatView_t* pView)
{
	SDL_Surface* pImageSurface = IMG_Load("res/app-background.png");
	if (pImageSurface == NULL)
	{
		TRACE("ShowFlatView() - Unable to load image.\n");
	}
	SDL_BlitSurface(pImageSurface, NULL, pScreen, NULL);
	if (pView->pLib != NULL)
	{
		TTF_Font* pFont = TTF_OpenFont(_gsz_FlatViewTextFont, _gi_FlatViewTextPtSize);
		TTF_Font* pSmallFont = TTF_OpenFont(_gsz_FlatViewSmallTextFont, _gi_FlatViewSmallTextPtSize);
		if ( (pFont != NULL) && (pSmallFont != NULL) )
		{
			int y = _gi_FlatViewPadding;
			int iIndex = 0;
			MediaFile_t* pFile = pView->pLib->pHead;

			while ( (pFile != NULL) && ((y+pView->ifHeight) < (pScreen->h-_gi_FlatViewPadding)) )
			{
				if (iIndex >= pView->iItemStart)
				{
					SDL_Color cText = _gc_FlatViewText;

					/* draws selection overlay */
					if (iIndex == pView->iItemSel)
					{
						SDL_Surface* pOverlaySurface = IMG_Load("res/select-overlay.png");
						if (pOverlaySurface != NULL)
						{
							SDL_Rect rcdst = { 0 , y + (pView->ifHeight - pOverlaySurface->h)/2 , 0, 0 };
							SDL_BlitSurface(pOverlaySurface, NULL, pScreen, &rcdst);
						}
						SDL_FreeSurface(pOverlaySurface);
						cText = _gc_FlatViewSelText;
					}
					if ((_gp_Current != NULL) && (_gp_Current == pFile))
					{
						cText = _gc_FlatViewPlayText;
					}

					/* draws text */
					SDL_Rect rcdst = { _gi_FlatViewPadding , y + _gi_FlatViewPadding, 0, 0 };
					SDL_Surface* pGlyph = TTF_RenderUTF8_Blended(pFont, _path_find_filename(pFile->pszFullPath), cText );
					SDL_BlitSurface(pGlyph, NULL, pScreen, &rcdst);

					/* draws sub text */
					SDL_Rect rcdst2 = { _gi_FlatViewPadding , y + 2*_gi_FlatViewPadding + pGlyph->h, 0, 0 };
					_path_extract_subfolder(pView->pLib->pszPath, pFile->pszFullPath, szSubFolder, SUBFOLDER_MAX_LEN);
					SDL_Surface* pSmallGlyph = TTF_RenderUTF8_Blended(pSmallFont, szSubFolder, cText);
					SDL_BlitSurface(pSmallGlyph, NULL, pScreen, &rcdst2);
					
					SDL_FreeSurface(pGlyph);
					SDL_FreeSurface(pSmallGlyph);

					y += pView->ifHeight + _gi_FlatViewItemYMargin;
				}
				pFile = pFile->pNext;
				iIndex++;
			}
			TTF_CloseFont(pFont);
			TTF_CloseFont(pSmallFont);
		}
	}
	SDL_UpdateRect(pScreen, 0, 0, _gi_AppWidth, _gi_AppHeight);
	SDL_FreeSurface(pImageSurface);
}

/*
 ------------------------------------------------------------------------------
	Scroll list

------------------------------------------------------------------------------
*/

static int _scroll_list(FlatView_t* pFlatView, int up)
{
	if (up)
	{
		if ((pFlatView->pLib != NULL) && (pFlatView->iItemSel > 0))
		{
			pFlatView->iItemSel--;
			if ( (pFlatView->iItemStart > 0) && (pFlatView->iItemSel < (pFlatView->iItemStart + _gi_ScrollThreshold)))
			{
				pFlatView->iItemStart--;
			}
			return 1;
		}
	}
	else
	{
		if ((pFlatView->pLib != NULL) && (pFlatView->iItemSel < (pFlatView->pLib->nFiles-1)))
		{
			pFlatView->iItemSel++;
			if ((pFlatView->iItemSel - pFlatView->iItemStart) >= (pFlatView->iItemsInPage - _gi_ScrollThreshold))
			{
				pFlatView->iItemStart++;
			}
			return 1;
		}
	}
	return 0;
}

static int FlatViewHandleUIMessage(View_t* pView, int msg, void* pData, long lParam)
{
	switch (msg)
	{
		case UI_SHOW:
			if (lParam)
			{
				ShowFlatView(pScreen, (FlatView_t*)pView);
			}
			break;

		default:
			break;
	}
	return 1;
}

static int FlatViewHandleEvent(View_t* pView, SDL_Event* pEvent)
{
	FlatView_t* pFlatView = (FlatView_t*)pView;
	if (pEvent->type == SDL_USEREVENT)
	{
		if (pEvent->user.code == EV_MEDIA_LIB_FOLDERS_READY)
		{
			TRACE("FlatViewHandleEvent() - received folders ready event.\n");
			pFlatView->pLib = (MediaLib_t*)pEvent->user.data1;
			if (pszFileToPlay != NULL)
			{
				int count = 0;
				MediaFile_t* pFile = pFlatView->pLib->pHead;
				while (pFile != NULL)
				{
					if (strcmp(pFile->pszFullPath, pszFileToPlay) == 0)
					{
						break;
					}
					pFile = pFile->pNext;
					count++;
				}
				if (pFile != NULL)
				{
					_gp_Current = pFile;
					_gp_Current->pDecodeData = _gp_Current->pDecoder->fpMediaDecode(pAudio, pFile->pszFullPath);
					while ( count !=  pFlatView->iItemSel )
					{
						_scroll_list(pFlatView, 0);
					}
					pFlatView->iItemStart += pFlatView->iItemSel - (pFlatView->iItemsInPage + 1);
				}
			}
			ShowFlatView(pScreen, (FlatView_t*)pView);
		}
		if (pEvent->user.code == EV_MEDIA_LIB_TAGS_READY)
		{
			TRACE("FlatViewHandleEvent() - received tags ready event.\n");
			/*pFlatView->pLib = (MediaLib_t*)pEvent->user.data1;
			ShowFlatView(pScreen, (FlatView_t*)pView);

			__TO_DO
			*/
		}
	}
	else if (pEvent->type == SDL_KEYUP)
	{
		if (pFlatView->nKeyRepeatCount > 0)
		{
			pFlatView->nKeyRepeatCount = 0;
		}
	}
	else if (pEvent->type == SDL_KEYDOWN)
	{
		pFlatView->nKeyRepeatCount++;
		if (	(pFlatView->nKeyRepeatCount <= _gi_KeyRepeatCountThreshold) 
			 && ((pFlatView->nKeyRepeatCount % _gi_KeyRepeatSlowMult) > 0)
			 && (pFlatView->nKeyRepeatCount > 1)	)
		{
			return 0;
		}

		switch (pEvent->key.keysym.sym)
		{
			case SDLK_ESCAPE:
				/* unstack */
				break;

			case SDLK_UP:
				if (_scroll_list(pFlatView, 1))
				{
					ShowFlatView(pScreen, pFlatView);
				}
				return 0;

			case SDLK_DOWN:
				if (_scroll_list(pFlatView, 0))
				{
					ShowFlatView(pScreen, pFlatView);
				}
				return 0;

			case SDLK_SPACE:
				if (pFlatView->pLib != NULL)
				{
					int count = 0;
					MediaFile_t* pFile = pFlatView->pLib->pHead;
					while ( (pFile != NULL) && (count < pFlatView->iItemSel) )
					{
						pFile = pFile->pNext;
						count++;
					}
					if (pFile != NULL)
					{
						/* _gp_Current is set:
							if _gp_Current->pDecodeData is NULL, not playing => play
							if _gp_Current->pDecodeData is not NULL, playing => switch track, resume or pause */
						if (_gp_Current != NULL)
						{
							/* means that current track is paused or playing */
							if (_gp_Current == pFile)
							{
								/* resume or pause */
								if (_gp_Current->pDecodeData->status == DECODE_STATUS_DECODING)
								{
									_gp_Current->pDecoder->fpMediaPause(_gp_Current->pDecodeData);
								}
								else
								{
									_gp_Current->pDecoder->fpMediaResume(_gp_Current->pDecodeData);
								}
								break;
							}
							else
							{
								/* current track should be stopped */
								_gp_Current->pDecoder->fpMediaStop(_gp_Current->pDecodeData);
							}
						}
						_gp_Current = pFile;
						_gp_Current->pDecodeData = _gp_Current->pDecoder->fpMediaDecode(pAudio, pFile->pszFullPath);
						ShowFlatView(pScreen, pFlatView);
					}
				}
				break;

			default:
				break;
		}
	}
	else if (pEvent->type == SDL_MOUSEBUTTONUP)
	{
		if (pEvent->button.button == SDL_BUTTON_LEFT)
		{
			int x, y, item;
			SDL_GetMouseState(&x, &y);
			item = _item_under_mouse(pFlatView, x, y);
			if (item != -1)
			{
				pFlatView->iItemSel = item;
				ShowFlatView(pScreen, pFlatView);
			}
		}
		else if (pEvent->button.button == SDL_BUTTON_WHEELUP)
		{
			if (_scroll_list(pFlatView, 1))
			{
				ShowFlatView(pScreen, pFlatView);
			}
		}
		else if (pEvent->button.button == SDL_BUTTON_WHEELDOWN)
		{
			if (_scroll_list(pFlatView, 0))
			{
				ShowFlatView(pScreen, pFlatView);
			}
		}
	}
	return 1;
}

View_t* CreateFlatView()
{
	FlatView_t* pOut = (FlatView_t*)malloc(sizeof(FlatView_t));
	if (pOut != NULL)
	{
		pOut->view.fpHandleEvent = FlatViewHandleEvent;
		pOut->view.fpHandleUIMessage = FlatViewHandleUIMessage;
		pOut->pLib = NULL;
		pOut->iItemStart = 0;
		pOut->iItemSel = 0;
		pOut->ifHeight = _gi_FlatViewItemHeight;
		pOut->iItemsInPage = ( (pScreen->h - 2 * _gi_FlatViewPadding) + _gi_FlatViewItemYMargin ) / (pOut->ifHeight + _gi_FlatViewItemYMargin);
		pOut->nKeyRepeatCount = 0;

		SDL_EnableKeyRepeat(_gi_KeyRepeatInitialDelay, _gi_KeyRepeatInterval);
	}
	return (View_t*)pOut;
}

void DestroyFlatView(View_t* pView)
{
	free(pView);
}

